/*
 * Copyright (C) 2016-2017 AnStudio
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.astudio.lhasa.modules.activities;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.Window;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.Toast;

import com.astudio.lhasa.R;
import com.astudio.lhasa.constants.Languages;
import com.astudio.lhasa.database.helpers.OfflineDictManager;
import com.astudio.lhasa.interfaces.IInterpreterCallback;
import com.astudio.lhasa.modules.views.InterpreterTextView;
import com.astudio.lhasa.utils.TextHelper;
import com.astudio.lhasa.workers.recognizers.SpeechInputRecognizer;
import com.astudio.lhasa.workers.synthesisers.OnlineSynthesiser;
import com.astudio.lhasa.workers.synthesisers.SynthesizerRole;
import com.astudio.lhasa.workers.translators.OnlineTranslator;
import com.astudio.lhasa.workers.translators.Translator;

import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Click;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.UiThread;
import org.androidannotations.annotations.ViewById;
import org.androidannotations.annotations.WindowFeature;


@EActivity(R.layout.activity_interpreter)
@WindowFeature(Window.FEATURE_NO_TITLE)
public class InterpreterActivity extends AppCompatActivity {

    private final int STATE_IDLE = 1;
    private final int STATE_LOADING_INPUT = 2;
    private final int STATE_LOADING_OUTPUT = 3;
    private final int STATE_READY = 4;

    private final int RECORD_PERMISSION_REQUEST_CODE = 10011;

    @ViewById(R.id.input)
    InterpreterTextView mTextInput;
    @ViewById(R.id.output)
    InterpreterTextView mTextOutput;
    @ViewById(R.id.voice_wave)
    ImageView mVoiceWaver;
    @ViewById(R.id.chinese)
    ImageView mIVChinese;
    @ViewById(R.id.tibetan)
    ImageView mIVTibetan;
    @ViewById(R.id.loading_input)
    View mIVLoadingInput;
    @ViewById(R.id.loading_onput)
    View mIVLoadingOutput;

    private boolean mIsListening = false;

    private Animation mRotateAnim = null;

    private int[] mVolumeRes = {R.drawable.mic_wave_0, R.drawable.mic_wave_1,
            R.drawable.mic_wave_2, R.drawable.mic_wave_3, R.drawable.mic_wave_4,
            R.drawable.mic_wave_5, R.drawable.mic_wave_6};

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    };

    private SpeechInputRecognizer mRecognizer  = null;
    private OnlineTranslator mTranslator  = null;
    private OnlineSynthesiser mSynthesiser = null;

    private IInterpreterCallback mCallback = new IInterpreterCallback() {
        @Override
        public void onRecognizeStart(int handler) {
            updateStateOnUI(STATE_LOADING_INPUT);
            updateTextView(mTextInput, "", false);
            updateTextView(mTextOutput, "", false);
        }

        @Override
        public void onRecognizeDone(int handler, String result, boolean isLast) {
            updateTextView(mTextInput, result, true);
            if (isLast) {
                String input = mTextInput.getText().toString();
                updateStateOnUI(STATE_LOADING_OUTPUT);
                boolean isTibetan = TextHelper.isTibetanCharacter(input);
                mTranslator.requestTranslateAsync(handler
                        , isTibetan? Translator.TRANSLATOR_DIRECTION_TB_TO_CHN: Translator.TRANSLATOR_DIRECTION_CHN_TO_TB
                        , input, this);
            }
        }

        @Override
        public void onTranslateStart(int handler, int srcLang, int dstLang, String input) {
        }

        @Override
        public void onTranslateDone(int handler, String result
                , int srcLang, int dstLang, String input) {
            updateTextView(mTextOutput, result, false);
            updateStateOnUI(STATE_READY);

            OfflineDictManager.getInstance().insertOrUpdate(input, result);
        }

        @Override
        public void onInterpreterError(int handler, int code, String error) {
            Toast.makeText(InterpreterActivity.this, "[code]" + code + "/n Error: " + error
                    , Toast.LENGTH_LONG).show();
            updateStateOnUI(STATE_IDLE);
        }

        @Override
        public void onVolumeChange(int handler, int i, byte[] bytes) {
            updateVoiceWave(i/7);
        }
    };

    @UiThread
    protected void updateStateOnUI(int state) {
        switch(state) {
            case STATE_IDLE:
                mTextInput.setVisibility(View.GONE);
                mTextOutput.setVisibility(View.GONE);
                mIVLoadingInput.setVisibility(View.GONE);
                mIVLoadingOutput.setVisibility(View.GONE);
                break;
            case STATE_LOADING_INPUT:
                mTextInput.setVisibility(View.GONE);
                mTextOutput.setVisibility(View.GONE);
                mIVLoadingInput.setVisibility(View.VISIBLE);
                mIVLoadingOutput.setVisibility(View.GONE);
                break;
            case STATE_LOADING_OUTPUT:
                mTextInput.setVisibility(View.VISIBLE);
                mTextOutput.setVisibility(View.GONE);
                mIVLoadingInput.setVisibility(View.GONE);
                mIVLoadingOutput.setVisibility(View.VISIBLE);
                break;
            case STATE_READY:
                mTextInput.setVisibility(View.VISIBLE);
                mTextOutput.setVisibility(View.VISIBLE);
                mIVLoadingInput.setVisibility(View.GONE);
                mIVLoadingOutput.setVisibility(View.GONE);
                break;
        }
    }

    @UiThread
    protected void updateTextView(InterpreterTextView view, String text, boolean append) {
        if (view == null) {
            return;
        }

        view.setText(text, append);
    }

    @UiThread
    protected void updateVoiceWave(int level) {
        mVoiceWaver.setImageResource(mVolumeRes[level]);
    }

    @AfterViews
    protected void bindViews() {
        mRecognizer = SpeechInputRecognizer.getInstance();
        mSynthesiser = OnlineSynthesiser.getSynthesizer();
        mTranslator = OnlineTranslator.getInstance();

        mTextInput.setType(true);
        mTextOutput.setType(false);

        mRotateAnim = AnimationUtils.loadAnimation(this, R.anim.ani_rotate);
        LinearInterpolator lin = new LinearInterpolator();
        mRotateAnim.setInterpolator(lin);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            int hasRecordPermission = checkSelfPermission(Manifest.permission.RECORD_AUDIO);
            if (hasRecordPermission != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}
                        , RECORD_PERMISSION_REQUEST_CODE);
            }
        }
    }

    @Click(R.id.chinese)
    protected void onInterpreterChinese() {
        if (mIsListening) {
            mIVChinese.clearAnimation();
            mVoiceWaver.setVisibility(View.GONE);
            mIVTibetan.setEnabled(true);
        } else {
            mIVTibetan.setEnabled(false);
            mVoiceWaver.setVisibility(View.VISIBLE);
            mIVChinese.startAnimation(mRotateAnim);
            mRecognizer.startListening(0, mCallback
                    , Languages.INTERPRETER_LANGUAGE_CHINESE_MANDARIN);
        }

        mIsListening = !mIsListening;
    }

    @Click(R.id.mapIndicator)
    protected void launchMapAssist(){
        Intent intent = new Intent();
        intent.setClass(this, MapSearchActivity_.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        startActivity(intent);
    }

    @Click(R.id.tibetan)
    protected void onInterpreterTibetan() {
        if (mIsListening) {
            mIVTibetan.clearAnimation();
            mRecognizer.stopListening();
            mVoiceWaver.setVisibility(View.GONE);
            mIVChinese.setEnabled(true);
        } else {
            mVoiceWaver.setVisibility(View.VISIBLE);
            mIVTibetan.startAnimation(mRotateAnim);
            mRecognizer.startListening(0, mCallback
                    , Languages.INTERPRETER_LANGUAGE_CHINESE_TIBETAN);
            mIVChinese.setEnabled(false);
        }

        mIsListening = !mIsListening;
    }

    @Click(R.id.output)
    protected void onSynthesis() {
        if (mTextOutput.getText() != null) {
            mSynthesiser.setRole(SynthesizerRole.SYNTHESIZER_ROLE_SDKAR);
            mSynthesiser.startSynthesize(0, mTextOutput.getText().toString());
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions
            , @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == RECORD_PERMISSION_REQUEST_CODE) {
            if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
                finish();
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
}
